<template>
  <DataTable url="codes/list" ref="ds" pageable>
    <template #search="{params,reload}">
      <Search v-model="params.id" placeholder="规则编号" @search="reload"/>
      <Search v-model="params.name" placeholder="规则名称" @search="reload"/>
    </template>
    <template #tools="table">
      <Button icon="jeicon-add" color="primary" @click="add">
        <Lang zh="新增"/>
      </Button>
      <Button :disabled="selects.length!=1" icon="h-icon-edit" text-color="primary" @click="editFirst">
        <Lang zh="修改"/>
      </Button>
      <Poptip :disabled="selects.length==0" class="h-btn" content="确定删除所选记录？" @confirm="del">
        <Button icon="h-icon-trash" text-color="red" :disabled="selects.length==0">
          <Lang zh="删除"/>
        </Button>
      </Poptip>
      <Button icon="h-icon-help" @click="showHelp=true"/>
    </template>
    <template #default="table">
      <Table ref="tb" :datas="table.data" :loading="table.loading" @trDblClick="edit" @select="selected" checkbox
             selectWhenClickTr>
        <TableItem :title="$t('序号','Serial')" prop="_index" :width="50"></TableItem>
        <TableItem :title="$t('规则编号','Rule Code')" prop="id" :width="200"></TableItem>
        <TableItem :title="$t('规则名称','Rule Name')" :width="220" prop="name"></TableItem>
        <TableItem :title="$t('备注','Memo')" prop="memo"></TableItem>
        <TableItem :title="$t('操作','Operation')" :width="120">
          <template #default="{data}">
            <div style="display: flex;justify-content: space-between;padding-right:10px">
              <i class="h-icon-edit link" @click="edit(data)"><Lang zh="修改"/></i>
              <Poptip content="确定删除所选记录？" @confirm="del">
                <i class="h-icon-trash link" style="color:red">
                  <Lang zh="删除"/>
                </i>
              </Poptip>
            </div>
          </template>
        </TableItem>
      </Table>
    </template>
  </DataTable>
  <Modal ref="dlg" v-model="codesDlg.show" hasDivider hasCloseIcon>
    <template #header>
      <Lang zh="编码规则" en="Coding Rule"/>
    </template>
    <div style="width:500px;">
      <div style="width: 500px;">
        <Form :model="formData" :rules="{}" mode="twocolumn" ref="formRef">
          <FormItem :label="$t('规则编号','Rule Code')" required>
            <Input type="text" :placeholder="$t('规则编号','Rule Code')" :readonly="codesDlg.codeReadOnly"
                   v-model="formData.id"/>
          </FormItem>
          <FormItem :label="$t('规则名称','Rule Name')" required>
            <Input type="text" :placeholder="$t('规则名称','Rule Name')" v-model="formData.name"/>
          </FormItem>
          <FormItem :label="$t('备注','Memo')" single>
            <Textarea type="text" :placeholder="$t('备注','Memo')" style="resize: none;width: 100%"
                      v-model="formData.memo"/>
          </FormItem>
        </Form>
      </div>
      <Divider>
        <Lang zh="编码规则" en="Coding rules"/>
      </Divider>
      <div style="padding-bottom: 10px;">
        <Button color="primary" icon="icon-add" @click="newRule">新增</Button>
      </div>
      <div style="width: 500px;height: 200px">
        <Table :datas="codesDlg.rules" :height="158" style="height: 200px">
          <TableItem :title="$t('类型','Type')" :width="70">
            <template #default="{data}">
              <Select :datas="codesTypes" v-model="data.type" @change="codeTypeChange(data)"/>
            </template>
          </TableItem>
          <TableItem :title="$t('值','value')" :width="100">
            <template #default="{data}">
              <Input v-model="data.value" style="width: 136px" @change="onCodeValueChange(data)"
                     :readonly="data.type =='S'||data.type =='U'"/>
            </template>
          </TableItem>
          <TableItem :title="$t('格式','Format')" :width="70">
            <template #default="{data}">
              <Select :datas="codesFormats" v-model="data.format" @change="onCodeFormatChange(data)"
                      :disabled="!(data.type =='S'||data.type =='U')"/>
            </template>
          </TableItem>
          <TableItem :title="$t('长度','Length')" :width="50">
            <template #default="{data}">
              <Input type="number" v-model="data.length" style="width:60px" :readonly="data.type != 'S'"/>
            </template>
          </TableItem>
          <TableItem :title="$t('操作','Operation')" :width="50" align="center">
            <template #default="{data}">
                <i class="h-icon-trash link" @click="delRule(data)"/>
            </template>
          </TableItem>
        </Table>
      </div>
    </div>
    <template #footer>
      <Button @click="codesDlg.show=false">
        <Lang zh="取消"/>
      </Button>
      <Button :loading="codesDlg.loading" color="primary" @click="saveCodes">
        <Lang zh="确认"/>
      </Button>
    </template>
  </Modal>
  <Modal  v-model="showHelp" hasDivider hasCloseIcon>
    <template #header>
      <Lang zh="帮助" en="Help"/>
    </template>
    <div>
      <pre>
        一、编码规则：
          1.常量：固定的输入值
          2.日期：根据输入的日期格式表达式输出获取编码时的日期
          3.雪花ID: 根据雪花算法获取的唯一ID，是一组长度为19位的数字，可根据编码格式缩短位数
          4.流水号：根据编码规则名称记录的顺序流水号
        二、编码格式：
          雪花ID和流水号可选择编码格式，其中：‘数字’表示获取的编码为纯数字、‘HEX’表示将数字转换为16进制表示、‘字符’表示将编码转换为数字和26个大写英文字母表示。
          常量和日期只根据规则的值来输出
        三、使用方法：
          1.手动获取编码，通过CodesService获取
            <code lang="java">
            CodesService codesService;

            String code=codeService.get("{规则编号}")
            </code>
          2.自动获取
            在需要获取编码的Domain字段上使用CodeIdGenerator编码器
            <code lang="java">
            public class TestCodesDomain implements Serializable {
                @BusinessId(generator = "com.rankeiot.platform.service.CodeIdGenerator",signature="{规则编号}")
                private String id;
            }
            </code>
            在使用dao.save(TestCodesDomain)保存数据时,如果对应字段(id),会根据规则自动生成编码
          3.前端使用
            使用CodesInput标签,标签属性和普通Input组件类似，通过指定code属性，在该规则被配置时，输入框会变为只读
            <code lang="html">
              简单使用：
              &lt;CodesInput code="{规则编号}"/>

              完整使用：

              const 规则是否配置=ref(false)
              &lt;CodesInput code="{规则编号}" v-model:configured="规则是否配置" placeholder="规则未配置时的提示" configuredPlaceholder="规则已配置时的提示"/>
            </code>
          四、其他：
            编码规则命名推荐以实体类名字+字段名，如：Student.number
            当编码规则中未配置规则时，视为未配置
      </pre>
    </div>
  </Modal>
</template>
<script setup>
import {ajax, util, default as framework} from 'framework'
import {ref, reactive, nextTick} from 'vue'
import {message} from 'heyui'
import {$t} from 'i18n'

//status
const showSearch = ref(false), selects = ref([]), dlg = ref(null),showHelp=ref(false)

const ds = ref(null), tb = ref()


function reload() {
  framework.cleanBranches()
  selects.value = []
  // table.load()
  ds.value.reload()
}

function search() {
  selects.value = []
  ds.value.reload()
}

function selected(v) {
  selects.value = v.map(it => Object.assign({}, it))
}

async function add() {
  codesDlg.codeReadOnly = false
  codesDlg.loading = false
  codesDlg.show = true
  util.clean(formData)
  codesDlg.rules = []
}

function editFirst() {
  if (selects.value.length == 0) {
    return;
  }
  edit(selects.value[0])
}

async function edit(v) {
  codesDlg.codeReadOnly = true
  codesDlg.loading = false
  codesDlg.show = true
  util.clean(formData)
  codesDlg.rules = []

  Object.assign(formData, v)
  if (v.rules) {
    let rules = JSON.parse(v.rules)
    for (let ruleStr of rules) {
      let item = {
        type: ruleStr.charAt(0),
        value: '',
        format: '36',
        length: '0'
      }
      switch (item.type) {
        case 'C'://常量
          item.value = ruleStr.substring(1);
          item.length = item.value.length
          break;
        case 'D':
          item.value = ruleStr.substring(1);
          item.length = item.value.length
          break;
        case 'U':
          item.value = '--';
          item.format = ruleStr.substring(1)
          item.length = SnowFormatLength[item.format]
          break;
        case 'S':
          let params = ruleStr.substring(1).split(":");
          item.value = '--';
          item.format = params[1];
          item.length = params[0];
          break
      }
      codesDlg.rules.push(item)
    }
  }

}

function del() {
  ajax.post('codes/delete', selects.value.map(it => ({id: it.id}))).then(r => {
    reload()
  })
}

function saveCodes() {
  codesDlg.loading = true
  let codes = codesDlg.rules.map(it => {
    if (!it.format) {
      it.format = '36'
    }
    if (!it.length) {
      it.length = 0
    }
    switch (it.type) {
      case 'C':
      case 'D':
        return it.type + it.value
      case 'U':
        return it.type + it.format
      case 'S':
        return it.type + it.length + ':' + it.format
    }
  })
  formData.rules = JSON.stringify(codes)

  ajax.post(codesDlg.codeReadOnly ? 'codes/save' : 'codes/add', formData).then(ret => {
    codesDlg.codeReadOnly = true
    message("已保存")
    reload()
  }).finally(_ => {
    codesDlg.loading = false
  })
}

/**==================form===================**/
const codesTypes = [
  {key: 'C', title: $t('常量', 'Const')},
  {key: 'D', title: $t('日期', 'Date')},
  {key: 'U', title: $t('雪花ID', 'Snowflake')},
  {key: 'S', title: $t('流水号', 'Serial')}
]
const codesFormats = [
  {key: '10', title: $t('数字', 'Number')},
  {key: '16', title: 'HEX'},
  {key: '36', title: $t('字符', 'Character')}
]
const SnowFormatLength = {
  '10': '19',
  '16': '16',
  '36': '12'
}
const formData = reactive({})

const codesDlg = reactive({
  rules: [],
  codeReadOnly: false,
  show: false,
  loading: false
})

function newRule() {
  codesDlg.rules.push({
    type: '',
    value: '',
    format: '',
    length: '0'
  })
}

function delRule(data) {
  let idx = codesDlg.rules.indexOf(data);
  if (idx > -1) {
    codesDlg.rules.splice(idx, 1)
  }
}

function codeTypeChange(data) {
  switch (data.type) {
    case 'C':
      data.value = '';
      data.length = '0'
      data.format = '36'
      break;
    case 'D':
      data.value = 'yyyyMMdd';
      data.length = '8'
      data.format = '36'
      break;
    case 'U'://雪花ID
      //19
      data.value = "--"
      data.format = '36'
      data.length = '12'
      break;
    case 'S'://流水号
      //19
      data.value = "--"
      data.format = '36'
      data.length = '4'
      break;
  }
}

function onCodeValueChange(data) {
  if (data.type == 'C' || data.type == 'D') {
    data.length = data.value.length
  }
}

function onCodeFormatChange(data) {
  if (data.type == 'U') {
    data.length = SnowFormatLength[data.format]
  }
}

</script>
